今天要分享的是關於 Angular 的 content projection。
Angular 提供了一個 ng-content 的 tag 來將其他的 HTML content 投影到 component template 內部,也就是標題所提到的 Content Projection。
來上個圖:
↑ Image 1:沒有使用 ng-content
↑ Image 2:使用 ng-content
Image 1 的右邊是沒有使用 ng-content 的 ProjectComponent HTML template,當其他的 component 使用 app-projection 這個 tag 的時候,不管在 app-project tag 的中間放多少個元素,最終渲染出來的結果依然是 HTML template 內已經寫好的樣子。所以當你有許多個 component 都會需要用到 ProjectComponent 但每次都會有一點不同的時候,你可能就會需要針對個別情況做不同的處理。
但如果採用像是 Image 2,使用 ng-content 的方式來設計 ProjectComponent 的話,你就可以將某些固定的元素寫進 ProjectComponent 的 HTML template 內,需要個別客製化的內容則是在該 component 做其他調整。
接下來要來介紹要如何使用多個 ng-content 來讓外部投影到內部的內容可以有更多的變化。
↑ Image 3:multi ng-content 的用法
當有多個 ng-content 存在於同一個 HTML template 的時候,我們可以透過 select
這個 attribute 來指定這個 ng-content 要投影外部的哪一個元素:
<ng-content select=".header"></ng-content>
↑ Block 1
以 Block 1 的程式碼範例來說,這個 ng-content 會選擇 CSS class
名稱符合 header
的元素來投影。
這邊給各位一個重點:select 接受任何符合 CSS selector 規範的字串。
所以我們可以像 Block 1 一樣用 .
來代表 class,也可以像下面一樣用 tag 或是 attribute:
<!-- 以 attribute 做選擇依據-->
<ng-content select="[footer]"></ng-content>
<!-- 以 tag 做選擇依據 -->
<ng-content select="p"></ng-content>
↑ Block 2
到這邊或許會有人好奇,當有多個元素符合 select 的話會怎麼樣?
答案是:都選,且按順序顯示。
<app-mproject>
<div footer>
<p>FOOTER</p>
</div>
<div class="header">
<p>HEADER</p>
</div>
<p>Not a footer is a p element</p>
<span>Third</span>
<p class="header">Second</p>
</app-mproject>
↑ Block 3:AppComponent HTML template
<div style="border: 2px solid orange; margin-top: 1px; padding: 1rem;">
<ng-content select=".header"></ng-content>
<div style="margin-left: 1rem">
<p>mproject works!</p>
</div>
<ng-content select="[footer]"></ng-content>
</div>
<ng-content select="p"></ng-content>
↑ Block 4:MprojectComponent HTML tempate
以 Block 3 與 Block 4 為例子來看的話,最終 render 的結果會是:
↑ Image 4
首先 <span>Third</span>
的部分不見了,因為在 MprojectionComponent 內並沒有任何的 ng-content 選取到這個元素,但若 template 內有一個 ng-content 不包含 selector 的話,這些被遺忘的元素就會被放到裡面。
接著看一下 select=".header"
的部分,符合的元素有兩個,一個是被包在 div 內的 p,另一個則是 <p>Second</p>
,這些符合 select 條件的元素都被按照出現的順序,全部被投影到最上面。再來是符合 select="[footer]"
的元素,最後則是符合 select="p"
的元素。
至於選擇的優先順序,相信不用我多說,各位也一定可以找出規律的!
以上就是今天要分享給各位的內容,明天會再接著探討 Angular 是怎麼解析以及處理 ng-content tag!
以下按照入團順序列出我們團隊夥伴的系列文章!
請自由參閱 ?